﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace DemoCore.Routings
{
    /// <summary>
    /// 
    /// </summary>
    public class HostManager
    {
        /// <summary>
        /// 
        /// </summary>
        public static HostManager Default = new HostManager();
        private HostInfo[] hosts = new HostInfo[0];
        private int[] indexs = new int[0];
        private object lockObj = new object();
        private Random random = new Random();

        /// <summary>
        /// 所有注册的Host
        /// </summary>
        public IList<HostInfo> Hosts
        {
            get
            {
                return this.hosts;
            }
        }

        /// <summary>
        /// 获取Host信息
        /// </summary>
        /// <returns></returns>
        public HostInfo GetHost()
        {
            HostInfo[] array = hosts.Where(p => p.IsActived && !p.IsStop).ToArray();
            if (array.Length == 0)
                return null;

            HostInfo result = null;
            double offset = random.NextDouble();
            double performances = array.Sum(p => p.Performance);
            double fromSection = 0.0;
            foreach (var hostInfo in array)
            {
                double weight = hostInfo.Performance / performances;//权重
                if (offset >= fromSection && offset < fromSection + weight)
                    result = hostInfo;
                fromSection += weight;
            }
            if (result == null)
                result = hosts.OrderBy(p => p.TotalFail).FirstOrDefault();

            return result;
        }

        /// <summary>
        /// 注册子服务
        /// </summary>
        /// <param name="subHost"></param>
        public void RegisterHost(SubHost subHost)
        {
            lock (lockObj)
            {
                List<HostInfo> source = new List<HostInfo>(hosts);
                HostInfo hostInfo = source.FirstOrDefault(p => p.Address.EqualsIgnoreCase(subHost.Address));
                if (hostInfo != null)
                {
                    hostInfo.Performance = subHost.Performance;
                    hostInfo.Fail = 0L;
                    hostInfo.IsActived = true;
                }
                else
                {
                    hostInfo = new HostInfo()
                    {
                        Address = subHost.Address,
                        Master = Dns.GetHostName(),
                        IsActived = true,
                        Performance = subHost.Performance,
                    };
                    source.Add(hostInfo);
                }
                hosts = source.Distinct(HostInfoComparer.Instance).ToArray();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="host"></param>
        public void Success(HostInfo host)
        {
            host.Success += 1;
            host.Fail = 0L;
        }

        /// <summary>
        /// Host请求失败
        /// </summary>
        /// <param name="host"></param>
        public void Faild(HostInfo host)
        {
            host.Fail++;
            host.TotalFail++;
            host.IsActived = false;
        }

        /// <summary>
        /// 更新Host信息
        /// </summary>
        /// <param name="hostInfo"></param>
        public void Update(HostInfo hostInfo)
        {
            var host = hosts.FirstOrDefault(p => p.Address.EqualsIgnoreCase(hostInfo.Address));
            if (host == null)
                return;
            host.IsActived = hostInfo.IsActived;
            host.Performance = hostInfo.Performance;
        }

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="address">服务地址</param>
        /// <returns></returns>
        internal bool Start(string address)
        {
            var hostInfo = hosts.FirstOrDefault(p => p.Address.EqualsIgnoreCase(address));
            if (hostInfo == null)
                return false;
            hostInfo.IsStop = false;
            return true;
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        /// <param name="address">服务地址</param>
        /// <returns></returns>
        internal bool Stop(string address)
        {
            var hostInfo = hosts.FirstOrDefault(p => p.Address.EqualsIgnoreCase(address));
            if (hostInfo == null)
                return false;
            hostInfo.IsStop = true;
            return true;
        }
    }
}
